#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import zipfile
import shutil
import imaplib
import email
from email.header import decode_header
import os

def read_emails(imap_server, username, password, folder='INBOX', save_attachments=True, download_dir='attachments'):
    """
    读取邮件功能

    :param imap_server: IMAP服务器地址
    :param username: 邮箱用户名
    :param password: 邮箱密码
    :param folder: 邮件文件夹，默认为INBOX
    :param save_attachments: 是否保存附件
    :param download_dir: 附件保存目录
    """
    # 连接到IMAP服务器
    mail = imaplib.IMAP4_SSL(imap_server)
    mail.login(username, password)
    mail.select(folder)

    # 搜索所有邮件
    status, messages = mail.search(None, 'ALL')
    message_ids = messages[0].split()

    if not os.path.exists(download_dir):
        os.makedirs(download_dir)

    for msg_id in message_ids:
        # 获取邮件数据
        status, msg_data = mail.fetch(msg_id, '(RFC822)')
        raw_email = msg_data[0][1]
        email_message = email.message_from_bytes(raw_email)

        # 解析邮件头
        subject, encoding = decode_header(email_message['Subject'])[0]
        if isinstance(subject, bytes):
            subject = subject.decode(encoding or 'utf-8')

        from_, encoding = decode_header(email_message['From'])[0]
        if isinstance(from_, bytes):
            from_ = from_.decode(encoding or 'utf-8')

        print(f"Subject: {subject}")
        print(f"From: {from_}")

        # 解析邮件正文
        if email_message.is_multipart():
            for part in email_message.walk():
                content_type = part.get_content_type()
                content_disposition = str(part.get('Content-Disposition'))
                try:
                    body = part.get_payload(decode=True).decode()
                except:
                    pass

                if content_type == 'text/plain' and 'attachment' not in content_disposition:
                    print(f"Body: {body}")
                elif 'attachment' in content_disposition:
                    filename = part.get_filename()
                    if filename:
                        filepath = os.path.join(download_dir, filename)
                        if save_attachments:
                            with open(filepath, 'wb') as f:
                                f.write(part.get_payload(decode=True))
                            print(f"Attachment saved: {filepath}")
        else:
            content_type = email_message.get_content_type()
            body = email_message.get_payload(decode=True).decode()
            if content_type == 'text/plain':
                print(f"Body: {body}")

        print("-" * 80)

    mail.logout()

def send_email(smtp_server, smtp_port, username, password,
               from_addr, to_addrs, cc_addrs, subject, body,
               attachment_paths, max_attachment_size_mb=10, delete_original=False):
    """
    发送邮件功能

    :param smtp_server: SMTP服务器地址
    :param smtp_port: SMTP服务器端口
    :param username: 邮箱用户名
    :param password: 邮箱密码
    :param from_addr: 发件人邮箱地址
    :param to_addrs: 收件人邮箱地址列表
    :param cc_addrs: 抄送人邮箱地址列表
    :param subject: 邮件主题
    :param body: 邮件正文
    :param attachment_paths: 附件路径列表
    :param max_attachment_size_mb: 最大附件大小（MB）
    :param delete_original: 是否删除原始附件文件
    """
    msg = MIMEMultipart()
    msg['From'] = from_addr
    msg['To'] = ', '.join(to_addrs)
    msg['Cc'] = ', '.join(cc_addrs)
    msg['Subject'] = subject

    msg.attach(MIMEText(body, 'plain'))

    for attachment_path in attachment_paths:
        if not os.path.exists(attachment_path):
            print(f"附件 {attachment_path} 不存在，跳过。")
            continue

        file_name = os.path.basename(attachment_path)
        file_size = os.path.getsize(attachment_path) / (1024 * 1024)

        if file_size > max_attachment_size_mb:
            compressed_path = compress_file(attachment_path)
            attachment_path = compressed_path
            file_name = os.path.basename(compressed_path)

        with open(attachment_path, "rb") as attachment:
            part = MIMEBase('application', 'octet-stream')
            part.set_payload(attachment.read())
            encoders.encode_base64(part)
            part.add_header('Content-Disposition', f"attachment; filename= {file_name}")
            msg.attach(part)

        if delete_original and file_name != os.path.basename(attachment_path):
            os.remove(attachment_path)

    with smtplib.SMTP(smtp_server, smtp_port) as server:
        server.starttls()
        server.login(username, password)
        server.sendmail(from_addr, to_addrs + cc_addrs, msg.as_string())

def compress_file(file_path, output_dir=None):
    """
    压缩文件

    :param file_path: 文件路径
    :param output_dir: 输出目录，默认与原文件同目录
    :return: 压缩后的文件路径
    """
    if output_dir is None:
        output_dir = os.path.dirname(file_path)

    base_name = os.path.basename(file_path)
    zip_name = f"{base_name}.zip"
    zip_path = os.path.join(output_dir, zip_name)

    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
        zipf.write(file_path, arcname=base_name)

    return zip_path

# 示例调用
if __name__ == "__main__":
    smtp_server = 'smtp.example.com'
    smtp_port = 587
    username = 'your_email@example.com'
    password = 'your_password'
    from_addr = 'your_email@example.com'
    to_addrs = ['recipient1@example.com', 'recipient2@example.com']
    cc_addrs = ['cc_recipient@example.com']
    subject = 'Test Email'
    body = 'This is a test email with attachments.'
    attachment_paths = ['path/to/attachment1.txt', 'path/to/attachment2.pdf']
    max_attachment_size_mb = 5
    delete_original = True

    send_email(smtp_server, smtp_port, username, password,
               from_addr, to_addrs, cc_addrs, subject, body,
               attachment_paths, max_attachment_size_mb, delete_original)